﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using JelleDruyts.Windows.Text;
using Schedulr.Models;

namespace Schedulr.Providers
{
    public static class TemplateTokenProvider
    {
        private static IDictionary<Type, object> sampleValues = new Dictionary<Type, object>();

        public static void SetSampleValue<T>(T sampleValue)
        {
            sampleValues[typeof(T)] = sampleValue;
        }

        public static void ProvideTemplateTokenValues(IDictionary<string, object> tokenValues, params object[] sourceValues)
        {
            var tokens = ProvideTemplateTokens(sourceValues).ToDictionary(i => i.Name, i => i.SampleValue);
            foreach (var token in tokens)
            {
                tokenValues.Add(token);
            }
        }

        public static IList<TemplateTokenInfo> ProvideTemplateTokens(IEnumerable<Type> sourceTypes)
        {
            return ProvideTemplateTokens(sourceTypes.Where(t => t != null && sampleValues.ContainsKey(t)).Select(t => sampleValues[t]));
        }

        public static IList<TemplateTokenInfo> ProvideTemplateTokens(IEnumerable<object> sourceValues)
        {
            var tokens = new List<TemplateTokenInfo>();
            if (sourceValues != null)
            {
                foreach (var value in sourceValues)
                {
                    if (value != null)
                    {
                        var sampleType = value.GetType();
                        // Skip if [Browsable(false)].
                        if (!sampleType.GetCustomAttributes(typeof(BrowsableAttribute), true).Cast<BrowsableAttribute>().Any(b => !b.Browsable))
                        {
                            foreach (var property in sampleType.GetProperties().OrderBy(p => p.Name))
                            {
                                // Skip if [Browsable(false)].
                                if (!property.GetCustomAttributes(typeof(BrowsableAttribute), true).Cast<BrowsableAttribute>().Any(b => !b.Browsable))
                                {
                                    // Prefix the token with the type name.
                                    var prefix = sampleType.Name;

                                    // Unless for a few cases that should use a modified prefix to make it cleaner.
                                    if (sampleType == typeof(ApplicationInfo))
                                    {
                                        prefix = "Application";
                                    }
                                    else if (sampleType == typeof(SchedulrConfiguration))
                                    {
                                        prefix = "Configuration";
                                    }
                                    tokens.Add(new TemplateTokenInfo(string.Format(CultureInfo.CurrentCulture, "{0}{1}", prefix, property.Name), property.GetValue(value, null)));
                                }
                            }
                        }
                    }
                }
            }
            return tokens;
        }
    }
}